﻿using System;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;

using CommunityServer.Components;

namespace CSLive.LiveSettings
{
    public class LiveSettings
    {
        #region Private Members

        private static LiveSettings _instance;
        private static readonly object _lock = new object();

        #endregion

        #region Contructor(s)

        protected LiveSettings()
        {
        }

        #endregion

        #region Public Methods

        /// <summary>
        /// Accessor to single instance of LiveSettings
        /// </summary>
        public static LiveSettings Instance()
        {
            if ( _instance == null )
            {
                lock ( _lock )
                {
                    if ( _instance == null )
                    {
                        _instance = new LiveSettings();
                    }
                }
            }

            return _instance;
        }

        /// <summary>
        /// Saves the settings to the database.
        /// </summary>
        /// <param name="settingsXML">CSLive settings represented in an xml file</param>
        public void SaveLiveSettings( string settingsXML )
        {
            using ( SqlConnection connection = GetSqlConnection() )
            {
                #region Attempt to open the connection

                try
                {
                    connection.Open();
                }
                catch ( Exception ex )
                {
                    throw new CSException( CSExceptionType.DataProvider, "Unable to open connection to data provider.", ex.InnerException );
                }

                #endregion

                SqlCommand command = new SqlCommand( "dbo.CSLive_Settings_Update", connection ) {CommandType = CommandType.StoredProcedure};
                command.Parameters.Add( "@SettingsXML", SqlDbType.NText ).Value = settingsXML;
                command.ExecuteNonQuery();

                // Explicitly close the connection if its open.
                if ( connection.State != ConnectionState.Closed )
                {
                    connection.Close();
                }
            }
        }

        /// <summary>
        /// Retrieves the Live Settings that are stored via XML in the database.
        /// </summary>
        /// <returns>Returns Live Settings that are stored via XML in the database if found; else returns String.Empty.</returns>
        public string GetLiveSettingsXML()
        {
            string settings = String.Empty;

            using ( SqlConnection connection = GetSqlConnection() )
            {
                #region Attempt to open the connection

                try
                {
                    connection.Open();
                }
                catch ( Exception ex )
                {
                    throw new CSException( CSExceptionType.DataProvider, "Unable to open connection to data provider.", ex.InnerException );
                }

                #endregion

                SqlCommand command = new SqlCommand( "dbo.CSLive_Settings_Get", connection ) {CommandType = CommandType.StoredProcedure};

                using ( SqlDataReader reader = command.ExecuteReader( CommandBehavior.CloseConnection ) )
                {
                    if ( reader != null && reader.HasRows && reader.Read() )
                    {
                        settings = reader[ "SettingsXML" ] as string;
                    }

                    // Explicitly close the reader if its open.
                    if ( reader != null && reader.IsClosed == false )
                    {
                        reader.Close();
                    }
                }

                // Explicitly close the connection if its open.
                if ( connection.State != ConnectionState.Closed )
                {
                    connection.Close();
                }
            }

            return settings;
        }

        #endregion

        #region Private Methods

        /// <summary>
        /// Returns a new SqlConnection.
        /// </summary>
        /// <returns>Returns a new SqlConnection Object if the ConnectionString is found; Throws Exception if not valid.</returns>
        private SqlConnection GetSqlConnection()
        {
            if ( !string.IsNullOrEmpty( ConnectionString ) )
            {
                return new SqlConnection( ConnectionString );
            }

            // Connection String wasn't found, so attempt to look it up.
            if ( ConfigurationManager.ConnectionStrings != null && ConfigurationManager.ConnectionStrings.Count > 0 )
            {
                ConnectionString = ConfigurationManager.ConnectionStrings[ "SiteSqlServer" ].ConnectionString;
                return new SqlConnection( ConnectionString );
            }

            // Could not find the connection string.
            throw new CSException( CSExceptionType.DataProvider, "SQL Connection String is invalid." );
        }

        #endregion

        #region Private Properties

        private string ConnectionString { get; set; }

        #endregion
    }
}